package com.junmeng.libadapter.base;

import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.core.view.GestureDetectorCompat;
import androidx.recyclerview.widget.RecyclerView;

/**
 * recyclerview item点击事件监听器，支持单击，长按，双击（双击需要配置）
 * 使用后item子view的监听事件都会被拦截,适用于只想响应item事件，却不触发item内部子view事件的情况
 * 示例：
 * recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(recyclerView) {
 *
 * @Override public void onItemClick(MotionEvent e, View view, int position) {}
 * })
 */
public class RecyclerItemClickListener extends RecyclerView.SimpleOnItemTouchListener {

    private GestureDetectorCompat mGestureDetector;
    private float mLastDownY;//上次down事件的y坐标
    private float mLastDownX;//上次down事件的x坐标
    private long mLastDownTime = 0L;//上次down事件开始时间
    private static long GUESS_TIME_WILL_LONG_CLICK = 50;//长按预估时间（单位毫秒），即如果手指在此时间内不动的话认为接下来大概率会触发长按事件(取值在50-100之间为宜)
    private static float DELTA_DISTANCE_WHEN_ACTION_UP = 10.0f;//在down和up之间距离误差，在此范围内可认为手指不动

    /**
     * 单击事件
     *
     * @param event
     * @param view
     * @param position
     */
    public void onItemClick(MotionEvent event, View view, int position) {
        //用户可覆盖此方法
    }

    /**
     * 长按事件
     *
     * @param event
     * @param view
     * @param position
     */
    public void onItemLongClick(MotionEvent event, View view, int position) {
        //用户可覆盖此方法
    }

    /**
     * 双击事件，{@link RecyclerItemClickListener#RecyclerItemClickListener(androidx.recyclerview.widget.RecyclerView, boolean)}第二参数为true时有效
     *
     * @param event
     * @param view
     * @param position
     */
    public boolean onItemDoubleClick(MotionEvent event, View view, int position) {
        //用户可覆盖此方法
        return false;
    }

    /**
     * 如果返回true,则子view的点击事件则不会响应，如果为false,则子view的点击事件和本监听器会同时触发，默认true
     *
     * @return
     */
    public boolean isInterceptChildClickEvent() {
        return true;
    }

    public RecyclerItemClickListener(final RecyclerView recyclerView) {
        this(recyclerView, false);
    }

    /**
     * @param recyclerView
     * @param isHandleDoubleClick 是否处理双击事件（之所以双击事件单独设置，是因为用户可能只想要单击事件同时还要处理快速点击的问题）
     */
    public RecyclerItemClickListener(final RecyclerView recyclerView, boolean isHandleDoubleClick) {
        GestureDetector.OnGestureListener onGestureListener;
        if (isHandleDoubleClick) {
            onGestureListener = new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onSingleTapConfirmed(MotionEvent e) {
                    handleItemClickEvent(e, recyclerView);
                    return true;
                }

                @Override
                public boolean onDoubleTap(MotionEvent e) {
                    View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
                    if (childView != null) {
                        int pos = recyclerView.getChildAdapterPosition(childView);
                        if (pos >= 0) {
                            return onItemDoubleClick(e, childView, pos);
                        }
                    }
                    return true;
                }

                @Override
                public void onLongPress(MotionEvent e) {
                    handleItemLongClickEvent(e, recyclerView);
                }
            };
        } else {
            onGestureListener = new SimpleOnGestureListener() {//使用GestureDetector.SimpleOnGestureListener的话会导致响应双击事件

                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    handleItemClickEvent(e, recyclerView);
                    return true;
                }

                @Override
                public void onLongPress(MotionEvent e) {
                    handleItemLongClickEvent(e, recyclerView);
                }
            };
        }

        mGestureDetector = new GestureDetectorCompat(recyclerView.getContext().getApplicationContext(), onGestureListener);

    }

    private void handleItemLongClickEvent(MotionEvent e, RecyclerView recyclerView) {
        View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
        if (childView != null) {
            int pos = recyclerView.getChildAdapterPosition(childView);
            if (pos >= 0) {
                onItemLongClick(e, childView, pos);
            }
        }
    }

    private void handleItemClickEvent(MotionEvent e, RecyclerView recyclerView) {
        View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
        if (childView != null) {
            int pos = recyclerView.getChildAdapterPosition(childView);
            if (pos >= 0) {
                onItemClick(e, childView, pos);
            }
        }
    }


    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        boolean touchConsumed = mGestureDetector.onTouchEvent(e);
//        Log.i("123456", "touchConsumed=" + touchConsumed + ",action=" + (e.getAction()& MotionEvent.ACTION_MASK) + ",x=" + e.getX() + ",y=" + e.getY());

        if (!isInterceptChildClickEvent()) {
            return false;
        }
        if ((e.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
            mLastDownY = e.getY();
            mLastDownX = e.getX();
            mLastDownTime = System.currentTimeMillis();
        }
        if ((e.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE
                && e.getX() == mLastDownX
                && e.getY() == mLastDownY
                && (System.currentTimeMillis() - mLastDownTime) > GUESS_TIME_WILL_LONG_CLICK
        ) {
            return true;//move一旦返回true,接下来的事件都会进入到onTouchEvent，直到另一个down事件
        }

        if ((e.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP
                && (e.getX() >= (mLastDownX - DELTA_DISTANCE_WHEN_ACTION_UP) && e.getX() <= (mLastDownX + DELTA_DISTANCE_WHEN_ACTION_UP))
                && (e.getY() >= (mLastDownY - DELTA_DISTANCE_WHEN_ACTION_UP) && e.getY() <= (mLastDownY + DELTA_DISTANCE_WHEN_ACTION_UP))
        ) {
            return true;//只在没有滑动时（误差范围内可认为没滑动）才拦截,这样子view就无法接收到up事件,从而不会触发子view的点击事件
        }
        return false;//必须返回false,否则事件都被拦截后recyclerview就无法滚动了
    }

    @Override
    public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
//        Log.i("123456", "onTouchEvent：action=" + e.getAction() + ",x=" + e.getX() + ",y=" + e.getY());
        //处理被拦截进来的事件
        mGestureDetector.onTouchEvent(e);
    }

    public static class SimpleOnGestureListener implements GestureDetector.OnGestureListener {

        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }

        public void onLongPress(MotionEvent e) {
        }

        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            return false;
        }

        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            return false;
        }

        public void onShowPress(MotionEvent e) {
        }

        public boolean onDown(MotionEvent e) {
            return false;//必须为false,否则会导致列表不可滑动
        }

    }
}